package com.mantbox.channelcall.utils;

import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class UaOsParser {

    // 正则表达式：匹配常见的User-Agent格式
    private static final String UA_PATTERN =
            "^[a-zA-Z0-9\\-\\.]+\\s*(\\([^()]+\\))?\\s*(.*)$";

    // 定义常见操作系统的正则模式
    // 优先级：iOS -> Android -> Windows -> Mac OS -> Linux
    private static final Pattern[] OS_PATTERNS = {
            // iOS: 匹配 iPhone OS 13_5, iOS 14.2 等格式
            Pattern.compile("(iPhone OS|iOS)[\\s_]([\\d_+]+)"),
            // Android: 匹配 Android 10, Android 9.0 等格式
            Pattern.compile("Android[\\s]([\\d.]+)"),
            // Windows: 匹配 Windows NT 10.0, Windows Phone 10.0 等格式
            Pattern.compile("(Windows NT|Windows Phone)[\\s]([\\d.]+)"),
            // Mac OS X: 匹配 Mac OS X 10_15_7, Intel Mac OS X 10_16 等格式
            Pattern.compile("(Mac OS X|Macintosh)[\\s]([\\d_]+)"),
            // Linux: 匹配 Linux x86_64, Linux i686 等 (通常没有明确版本号)
            Pattern.compile("Linux"),
            //获取安卓设备型号
            Pattern.compile("Build/([^;)]+)")
    };

    /**
     * 从 User-Agent 字符串中解析操作系统名称和版本
     *
     * @param userAgent User-Agent 字符串
     * @return OsInfo 对象，包含系统名称和版本（如果解析失败则返回未知信息）
     */
    public static OsInfo parseOs(String userAgent) {
        if (userAgent == null || userAgent.isEmpty()) {
            return new OsInfo("Unknown", "Unknown");
        }

        String ua = userAgent.toLowerCase(Locale.ENGLISH);

        // 按优先级尝试匹配各种系统
        for (Pattern pattern : OS_PATTERNS) {
            Matcher matcher = pattern.matcher(userAgent); // 注意：对原始UA匹配，大小写敏感
            if (matcher.find()) {
                return buildOsInfo(matcher, ua);
            }
        }

        // 如果以上都没匹配到，返回未知
        return new OsInfo("Unknown", "Unknown");
    }

    private static OsInfo buildOsInfo(Matcher matcher, String ua) {
        String osName;
        String osVersion = "Unknown";

        switch (matcher.pattern().toString()) {
            case "(iPhone OS|iOS)[\\s_]([\\d_+]+)":
                osName = "iOS";
                if (matcher.groupCount() >= 2) {
                    osVersion = matcher.group(2).replace('_', '.');
                }
                break;
            case "Android[\\s]([\\d.]+)":
                osName = "Android";
                if (matcher.groupCount() >= 1) {
                    osVersion = matcher.group(1);
                }
                break;
            case "(Windows NT|Windows Phone)[\\s]([\\d.]+)":
                // 判断是Windows PC还是Windows Phone
                if (matcher.group(1).contains("Phone")) {
                    osName = "Windows Phone";
                } else {
                    osName = "Windows";
                }
                if (matcher.groupCount() >= 2) {
                    osVersion = matcher.group(2);
                    // 将Windows NT版本映射为常见版本名
                    osVersion = mapWindowsVersion(osVersion);
                }
                break;
            case "(Mac OS X|Macintosh)[\\s]([\\d_]+)":
                osName = "macOS";
                if (matcher.groupCount() >= 2) {
                    String rawVersion = matcher.group(2).replace('_', '.');
                    osVersion = mapMacOsVersion(rawVersion);
                }
                break;
            case "Linux":
                osName = "Linux";
                // Linux UA通常不包含版本号，可以尝试进一步解析发行版
                osVersion = parseLinuxDistribution(ua);
                break;
            default:
                osName = "Unknown";
        }

        return new OsInfo(osName, osVersion);
    }

    /**
     * 将 Windows NT 版本号映射为通俗名称
     */
    private static String mapWindowsVersion(String ntVersion) {
        switch (ntVersion) {
            case "10.0": return "10 or Server 2016";
            case "6.3": return "8.1 or Server 2012 R2";
            case "6.2": return "8 or Server 2012";
            case "6.1": return "7 or Server 2008 R2";
            case "6.0": return "Vista or Server 2008";
            case "5.2": return "XP x64 or Server 2003";
            case "5.1": return "XP";
            case "5.0": return "2000";
            default: return ntVersion;
        }
    }

    /**
     * 简化 Mac OS X 版本号
     */
    private static String mapMacOsVersion(String rawVersion) {
        // 简单处理：10.15.7 -> 10.15
        if (rawVersion.startsWith("10.")) {
            int secondDot = rawVersion.indexOf('.', 3);
            if (secondDot > 0) {
                return rawVersion.substring(0, secondDot);
            }
        }
        return rawVersion;
    }

    /**
     * 尝试解析 Linux 发行版信息
     */
    private static String parseLinuxDistribution(String ua) {
        if (ua.contains("ubuntu")) return "Ubuntu";
        if (ua.contains("debian")) return "Debian";
        if (ua.contains("fedora")) return "Fedora";
        if (ua.contains("centos")) return "CentOS";
        if (ua.contains("red hat")) return "RedHat";
        return "Unknown Distribution";
    }

    /**
     * 操作系统信息封装类
     */
    public static class OsInfo {
        private final String name;
        private final String version;

        public OsInfo(String name, String version) {
            this.name = name;
            this.version = version;
        }

        public String getName() {
            return name;
        }

        public String getVersion() {
            return version;
        }

        @Override
        public String toString() {
            return name + " " + version;
        }
    }

    /*
    * 校验是否合规
    * */
    public static boolean isValidUA(String userAgent) {
        if (userAgent == null || userAgent.trim().isEmpty()) {
            return false;
        }

        Pattern pattern = Pattern.compile(UA_PATTERN);
        Matcher matcher = pattern.matcher(userAgent);
        return matcher.matches();
    }

    /*
    * 获取设备型号
    * */
    public static String androidModel(String ua) {
        Pattern pattern = OS_PATTERNS[5];
        Matcher matcher = pattern.matcher(ua);
        if (matcher.find()) {
            String deviceModel = matcher.group(1);
            return deviceModel;
        }
        return "";
    }
}